<template>
  <!--
  • 增强型链接组件，集成路由智能识别、样式扩展、链接状态验证及下载属性增强功能
  • @extends {ElLink}
  -->
  <component
      :is="linkComponent"
      v-bind="combinedProps"
      :class="computedClass"
      :style="combinedStyle"
      v-on="$listeners"
      @click="handleClick"
  >
    <!-- 徽标容器 -->
    <el-badge
        v-if="showBadge"
        :value="badgeValue"
        :max="badgeConfig.max"
        :type="badgeConfig.type"
        class="el-link-plus-badge"
    >
      <!-- 内容容器 -->
      <span class="el-link-plus-content">
        <!-- 前置图标 -->
        <template v-if="preIcon">
          <i :class="preIcon" class="el-link-plus-icon" />
        </template>
        <!-- 透传所有插槽内容 -->
        <slot name="icon" />
        <slot />
        <!-- 后置图标 -->
        <template v-if="postIcon">
          <i :class="postIcon" class="el-link-plus-icon" />
        </template>
      </span>
    </el-badge>
    <template v-else>
      <!-- 无徽标时的内容 -->
      <template v-if="preIcon">
        <i :class="preIcon" class="el-link-plus-icon" />
      </template>
      <slot name="icon" />
      <slot />
      <template v-if="postIcon">
        <i :class="postIcon" class="el-link-plus-icon" />
      </template>
    </template>
  </component>
</template>

<script>
/**
 * 路由链接增强组件
 * @module components/ElLinkPlus
 */
import {Link} from 'element-ui';
import {isExternal} from '@/utils/validate';
import axios from 'axios';

export default {
  name: 'ElLinkPlus',
  components: {ElLink: Link},
  inheritAttrs: false,
  props: {
    /**
     * 启用自适应宽度模式（根据内容自动调整）
     * @type {Boolean}
     * @default false
     */
    adaptiveWidth: {
      type: Boolean,
      default: false
    },
    /**
     * 超出容器时显示省略号
     * @type {Boolean}
     * @default false
     */
    ellipsis: {
      type: Boolean,
      default: false
    },
    /**
     * 徽标配置
     * @type {number|Object}
     * @property {number} value - 显示的数字值
     * @property {number} [max=99] - 最大值，超过显示 {max}+
     * @property {string} [type='danger'] - 徽标类型（primary/success/warning/danger/info）
     * @example 数字形式: :badge="5"
     * @example 对象形式: :badge="{ value: 10, max: 9, type: 'warning' }"
     */
    badge: {
      type: [Number, Object],
      default: null
    },
    /**
     * 启用路由预加载功能
     * @type {boolean}
     * @property {Boolean} preloadOnHover - 是否在 hover 时预加载目标路由资源
     * @example
     * <el-link-plus :preloadOnHover="true" />
     */
    preloadOnHover: {
      type: Boolean,
      default: false
    },
    to: {
      type: [String, Object],
      default: null
    },
    href: {
      type: String,
      default: null
    },
    routerMode: {
      type: String,
      default: 'auto',
      validator: v => ['hash', 'history', 'auto'].includes(v)
    },
    preIcon: {
      type: [String, Object],
      default: null
    },
    postIcon: {
      type: [String, Object],
      default: null
    },
    hoverEffect: {
      type: Boolean,
      default: false
    },
    customClass: {
      type: [String, Array, Object],
      default: null
    },
    customStyle: {
      type: [String, Array, Object],
      default: null
    },
    downloadFilename: {
      type: String,
      default: null
    },
    isExternalDownloadLink: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      isLinkValid: true
    };
  },
  computed: {
    // 新增容器相关计算属性
    containerClass() {
      return [
        'el-link-plus-container',
        {
          'adaptive-width': this.adaptiveWidth,
          'ellipsis-mode': this.ellipsis
        }
      ];
    },
    containerStyle() {
      return this.adaptiveWidth
          ? { maxWidth: '100%' } // 限制最大宽度
          : {};
    },
    /** 是否显示徽标 */
    showBadge() {
      return this.badge  !== null && this.badge  !== undefined
    },

    /** 徽标数值 */
    badgeValue() {
      return typeof this.badge  === 'object' ? this.badge.value  : this.badge
    },

    /** 徽标配置 */
    badgeConfig() {
      const defaults = { max: 99, type: 'danger' }
      if (typeof this.badge  === 'object') {
        return { ...defaults, ...this.badge  }
      }
      return defaults
    },
    // 修改原有class计算逻辑
    computedClass() {
      return [
        this.$attrs.class,
        this.customClass,
        { 'el-link-plus--hover-effect': this.hoverEffect  },
        { 'el-link-plus--invalid': this.isExternalDownloadLink  && !this.isLinkValid  && (this.isExternalLink  || this.to)  },
        { 'text-ellipsis': this.ellipsis  } // 文本省略号样式
      ].filter(Boolean);
    },
    combinedStyle() {
      return [this.$attrs.style, this.customStyle].filter(Boolean);
    },
    combinedProps() {
      const {class: _, style: __, ...attrs} = this.$attrs;
      const base = {
        ...attrs,
        ...this.linkSpecificProps
      };
      const props = this.isExternalLink ? {
        ...base,
        href: this.actualHref,
        rel: 'noopener noreferrer'
      } : base;
      if ((this.isExternalDownloadLink || this.isFileLink) && this.isLinkValid) {
        props.download = this.downloadFilename || this.getFileNameFromUrl(this.actualHref);
      }
      return props;
    },
    isHashMode() {
      if (this.routerMode === 'auto') {
        return this.$route.fullPath.startsWith('#/') || window.location.hash.includes('#/');
      }
      return this.routerMode === 'hash';
    },
    linkComponent() {
      if (this.isExternalLink) return 'a';
      return this.to ? 'router-link' : 'el-link';
    },
    isExternalLink() {
      return isExternal(this.href) || (this.href && !this.to) || isExternal(this.to?.path || this.to);
    },
    linkSpecificProps() {
      if (this.isExternalLink) {
        return {target: '_blank', rel: 'noopener noreferrer'};
      }
      return this.to ? {to: this.normalizedTo} : {};
    },
    normalizedTo() {
      if (!this.to) return null;
      if (typeof this.to === 'string') {
        return this.isHashMode ? `#${this.to}` : this.to;
      }
      return {
        ...this.to,
        path: this.isHashMode ? `#${this.to.path}` : this.to.path
      };
    },
    actualHref() {
      if (this.href) return this.href;
      if (typeof this.to === 'string') return this.to;
      return this.to?.path || '';
    },
    isFileLink() {
      const fileExtensions = ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.zip', '.rar'];
      return fileExtensions.some(ext => this.actualHref.endsWith(ext)) && this.isLinkValid;
    }
  },
  created() {
    this.validateLink();
  },
  methods: {
    /**
     * 处理鼠标悬停事件，触发路由预加载
     * @method handleHover
     * @description 当 preloadOnHover 为 true 时，通过 router.preload()  预加载目标路由资源
     * @listens mouseenter
     */
    handleHover() {
      console.log('鼠标悬停事件触发')
      if (this.preloadOnHover) {
        console.log(' 预加载路由:', this.normalizedTo);
        try {
          const resolved = this.$router.resolve(this.normalizedTo)
          if (resolved.route.matched.length  > 0) {
            // 预加载路由组件（需配合 () => import() 语法使用）
            resolved.route.matched.forEach(match  => {
              if (typeof match.components.default  === 'function') {
                match.components.default()
              }
            })
          }
          console.log(` 预加载路由 ${this.normalizedTo} 成功`);
        } catch (error) {
          console.warn(' 路由预加载失败:', error);
        }
      }
  },
  getFileNameFromUrl(url) {
    return url.split('/').pop();
  },
  async validateLink() {
    if (this.isExternalDownloadLink) {
      try {
        await axios.head(this.actualHref);
        this.isLinkValid = true;
      } catch (error) {
        this.isLinkValid = false;
        console.error(` 链接 ${this.actualHref}  无效:`, error);
      }
    } else if (this.to) {
      const route = this.$router.resolve(this.normalizedTo);
      this.isLinkValid = route.resolved.matched.length > 0;
      if (!this.isLinkValid) {
        console.error(` 路由 ${this.normalizedTo}  无效`);
      }
    }
  },
  /**
   * 处理点击事件，增加 before-click 和 after-click 生命周期事件
   * @param {Event} e - 点击事件对象
   */
  async handleClick(e) {
    if (!this.isLinkValid) {
      e.preventDefault();
      alert('链接无效，请检查！');
      return;
    }

    // 触发 before-click 事件
    const beforeClickResult = this.$emit('before-click', e);
    if (beforeClickResult === false) {
      // 如果 before-click 事件返回 false，则阻止后续操作
      e.preventDefault();
      return;
    }

    if (this.isExternalLink) {
      if (this.actualHref) {
        if (this.isExternalDownloadLink) {
          const a = document.createElement('a');
          a.href = this.actualHref;
          a.download = this.downloadFilename || this.getFileNameFromUrl(this.actualHref);
          document.body.appendChild(a);
          a.click();
          document.body.removeChild(a);
          e.preventDefault();
        } else {
          window.open(this.actualHref, '_blank');
          e.preventDefault();
        }
      }
    } else if (this.to) {
      this.$router.push(this.normalizedTo);
    }

    // 延迟触发 after-click 事件
    setTimeout(() => {
      this.$emit('after-click', e);
    })
  }
}
}
;
</script>

<style scoped>
.el-link-plus-icon {
  margin-right: 4px;
}

.el-link-plus-icon-spacing {
  display: inline-block;
  width: 4px;
}

.el-link-plus-icon {
  margin-right: 4px;
  transition: color 0.3s ease;
}

.el-link-plus--hover-effect {
  position: relative;
  transition: color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
  opacity 0.3s ease;
}

.el-link-plus--hover-effect::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 2px;
  background-color: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.el-link-plus--hover-effect:hover::after {
  transform: scaleX(1);
  transform-origin: left;
}

.el-link-plus--hover-effect:hover {
  color: var(--el-color-primary) !important;
}

.el-link-plus--invalid {
  color: #ccc;
  cursor: not-allowed;
}
/* 新增徽标样式 */
.el-link-plus-badge {
  vertical-align: middle;
}

.el-link-plus-content {
  position: relative;
  display: inline-flex;
  align-items: center;
}

::v-deep .el-badge__content {
  top: -8px;
  right: -12px;
  transform: scale(0.85);
}

/* 原有样式保持不变 */
.el-link-plus-icon {
  margin-right: 4px;
}
/* 新增容器样式 */
.el-link-plus-container {
  display: inline-block;
  vertical-align: middle;
}

/* 自适应宽度模式 */
.el-link-plus-container.adaptive-width  {
  width: auto;
  max-width: 100%;
}

/* 省略号模式 */
.el-link-plus-container.ellipsis-mode  {
  width: 100%;
  overflow: hidden;
}

.text-ellipsis {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  display: inline-block;
  max-width: 100%;
}
</style>